﻿using JESAI.HttpRequestMonitor.Options;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Http.Features;
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Runtime.CompilerServices;
using System.Text;
using System.Threading.Tasks;

namespace JESAI.HttpRequestMonitor.Utils
{
    public static class HttpRequestUtil
    {
        public static bool FilterRequest(HttpContext context, HttpRequestMonitorOptions options)
        {
            if (options.FilterRequest == null || options.FilterRequest.Count() == 0)
            {
                return false;
            }

            var path = context.Request.Path.Value.ToLowerInvariant();

            return MatchRequestMonnitorRule();

            bool MatchRequestMonnitorRule()
            {
                bool rtn = false;

                foreach (var request in options.FilterRequest)
                {
                    var rule = request.ToLowerInvariant();

                    if (rule.Select(x => x == '%').Count() == 0)
                    {
                        continue;
                    }
                    else if (rule.Select(x => x == '%').Count() >= 2)
                    {
                        if (path.Contains(rule.Replace("%", "")))
                        {
                            return true;
                        }
                    }
                    else if (rule.Select(x => x == '%').Count() == 1 && rule.LastOrDefault() == '%')
                    {
                        if (path.StartsWith(rule.Replace("%", "")))
                        {
                            return true;
                        }
                    }
                    else if (rule.Select(x => x == '%').Count() == 1 && rule.FirstOrDefault() == '%')
                    {
                        if (path.EndsWith(rule.Replace("%", "")))
                        {
                            return true;
                        }
                    }
                }

                return rtn;
            }
        }

        public static async Task<string> GetRequestBodyAsync(HttpContext context)
        {
            try
            {
                string rtn = string.Empty;
                context.Request.EnableBuffering();
                var requestReader = new StreamReader(context.Request.Body, System.Text.Encoding.UTF8);

                rtn = await requestReader.ReadToEndAsync();

                context.Request.Body.Position = 0;

                return rtn;
            }
            catch
            {
                return string.Empty;
            }
        }

        public static bool FilterStaticFiles(this HttpContext context)
        {
            if (!context.Request.ContentType.IsEmpty() && context.Request.ContentType.Contains("application/grpc"))
            {
                return false;
            }

            if (context.Request.Method.ToLowerInvariant() == "options")
            {
                return true;
            }

            return false;
        }

        public async static Task<string> GetResponseBodyAsync(this HttpContext context)
        {
            try
            {
                if (FilterStaticFiles(context))
                {
                    context.Response.Body.Seek(0, SeekOrigin.Begin);
                    return string.Empty;
                }

                string result = string.Empty;

                context.Response.Body.Seek(0, SeekOrigin.Begin);

                var responseReader = new StreamReader(context.Response.Body, System.Text.Encoding.UTF8);

                result = await responseReader.ReadToEndAsync();

                context.Response.Body.Seek(0, SeekOrigin.Begin);

                return result;
            }
            catch (Exception ex)
            {
                return string.Empty;
            }
        }
    }
}
